#include <stdlib.h>
#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

//要求：只能创建堆对象，不能创建栈对象
//解决方案：将析构函数设置为私有的，然后提供销毁堆对象的函数
//destroy，在其中执行销毁操作
class Student
{
public:
    Student(int id, const char *name)
    : _id(id)
    , _name(new char[strlen(name) + 1]())
    {
        cout << "Student(int, const char *)" << endl;
        strcpy(_name, name);
    }

    static void *operator new(size_t sz)
    {
        cout << "void *operator new(size_t )" << endl;
        void *pret = malloc(sz);
        return pret;
    }
    static void operator delete(void *pst)
    {
        cout << "void operator delete(void *)" << endl;
        free(pst);
    }

    void print() const
    {
        if(_name)
        {
            cout << "_id = " << this->_id << endl
                 << "_name = " << _name << endl;
        }
    }

    void destroy()
    {
        //问题1：能不能再此处直接执行析构函数呢？
        //答案：直接执行析构函数只能将对象中数据成员申请
        //的资源回收，并不能将堆对象本身占用的空间回收
        //
        /* this->~Student(); */
        //问题2：本函数的作用就是为了解决delete pstu
        //因为pstu是指向new Student的指针
        //答案：在类中this指针是记录对象地址的，所以
        //可以直接delete this就可以了
        delete this;
    }
private:
    ~Student()
    {
        cout <<"~Student()" << endl;
        if(_name)
        {
            delete [] _name;
            _name = nullptr;
        }
    }
private:
    int _id;
    char *_name;
};

void test()
{
    //1、创建栈对象需要有哪些条件呢？
    //答案：构造函数与析构函数都要是public的
    /* Student stu(1234, "xiaoming");//error */
    /* stu.print(); */

    Student *pstu = new Student(4201, "xiaohong");//ok
    pstu->print();

    //2、析构函数的执行与对象的销毁是不是一回事呢？
    //答案：对于堆对象而言，析构函数只是对象销毁中的一部分；
    //但是对于栈对象而言，析构函数与对象的销毁是一回事
    pstu->destroy();
    /* delete pstu;//error */
    /* pstu = nullptr; */
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

